函式返回值為物件時的寫法
const userData = user => ({ name: user.name, age: user.age });
參數為物件
//原本寫法
const userData = user => ({ name: user.name, age: user.age });
//解構賦值,先將 name, age 解構取出,就可以賦值使用
const userData = ({name, age}) => ({name, age});
參數為陣列
const test = ([x, y]) => x + y;
JS 函式是先定義後調用,如下
function test(x, y) {
return x + y;
};
test(1, 2);//3
也允許在函式中嵌入函數做使用
function test1(x, y) {
function test2(x, y) {
return x + y;
};
return test2(3, 3) + test2(x, y);
};
test1(4, 4);//14
在箭頭函式中,嵌套如下
const test1 = x => y => x + y;
//等於下面這種
function test1(x) {
return function test2(y) {
return x + y;
};
};
ES6 新增了 class 作為 ES5 中原型寫法的一個語法糖,相較原型鍊的寫法,class 能夠更簡潔易懂的達到繼承的目的。
首先要定義一個 class,並定義構造函數。如果 class 內沒有定義構造函數,則默認 class 的構造函數 counstuctor 為空函數,即使沒寫也會存在,只是不會顯示。
class Count {}
// counstuctor 即使沒寫也會存在,只是不會顯示
class Count {
constructor() {
}
}
定義 class 之後,可以透過 new 生成實例
class Count {
constructor(x, y) {
this.x = x
this.y = y
}
todoString () {
return this.x + this.y
}
}
//生成實例
const a = new Count(1, 2)
上面 class 的寫法實際上等同於下面 ES5 的寫法
function Count(x, y) {
this.x = x
this.y = y
}
Count.prototype.todoString = function () {
return this.x + this.y
}
var a = new Count(1, 2)
要在 class 裡面定義屬性,必須在構造函數中去宣告,定義函數也是。
class Profile {
constructor () {
this.state = {
name: null
}
this.getName = this.getName.bind()
}
getName () {
//...
}
}
上述定義 class 屬性的方式比較麻煩,所以 ES7 推出了另一個定義方法,class properties proposal,可以省略 constructor,在 class 內直接定義屬性
class Profile {
state = {
name: null
}
getName () {
//...
}
}
class properties proposal 在 react 中的應用
class Profile extends Component {
state = {
name: leo,
age: 29,
gender: male
}
render () {
const {name, age, gender} = this.state
return <div>
{name}, 今年 {age}
</div>
}
使用 static 定義 class 的靜態方法,不需要實例化也能訪問
class Profile {
static getName (name) {
return name
}
static gender = 'male'
}
const P = Profile.getName('ben') //不需要實例化就能使用
const gender = Profile.gender
class 可以透過 extends 來繼承,比 ES5 透過原型鍊修改來繼承更為方便易懂。會在 constructor 透過一個叫 super 的 function 去實現繼承。super 是調用父 class,但它的 this 則指向子 class,必須在使用 super 後才能使用 this。
class A {}
class B extends A { //繼承 A
constructor () {
console.log(this) // 報錯
super ()//用來實現繼承的內建方法
console.log(this) // 正確
}
}
class properties proposal 中會自動綁定繼承,所以一樣可以省略 super
class A {
state = {
age: 30
};
};
class B extends A { //繼承 A
state = {
userAge = this.state.age // age 已經被繼承,可以直接訪問, this 指向 B
};
};
const P = new B() // 實例化
console.log(P.state.userAge) //30
Decorator 是 ES7 新增的一個特性,主要用於 class 的行為,只能用於 class 和 class 的方法,不能用於函式。
Decorator 實際上是一個函式,接受 class 作為參數,如下
function annotation (target) {
target.annotated = true; //給 target class 增加 annotated 的屬性
target.state = { //給 target class 增加 state 物件
name: 'leo'
};
};
// 使用修飾器時要放在 class 的頂部,或是類的方法的頂部
@annotation
class Profile {
@annotation //也可以用於修改 class 的方法
getName(name) {
return name;
};
};
// 可以調用到新的屬性
console.log(Profile.annotated);
console.log(Profile.state);
附帶一提,decorator 需要 babel 插件的支持,create-react-app,本身支持。
@babel/plugin-proposal-decorators
這邊課程中以 mobx 為例,mobx 是 react 中常用的資料狀態管理方法之一,它應用了 decorator 來結合 store 和元件,範例如下
import React, { Component } from 'react';
// inject, observer 都是 mobx 本身封裝的修飾器
import { inject, observer } from 'mobox-react';
@inject('store') //傳入 store
@observer //觀察元件狀態的變更
class SchoolComponent extends Component {
state = {
schoolName: this.props.store.school.name // store 是透過修飾器傳入
}
render () {
return (
<div>學校:{this.state.schoolName}</div>
)
}
}
課程中建議不要大量使用 decorator,因為隨著 react hook 的推出,很多開發者更傾向於函式組件的寫法,而 decotator 主要應用於 class,因此往後的使用將會慢慢減少。
今天整理了一直以來不大清楚的 class 和 decorator,下一篇會是最後一篇和 ES6 相關,是整理我看過很多次,觀念上卻還是常常混淆不清的 promise 以及 await async。